Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle queries on non-existing table gracefully #3869

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

taimoorzaeem
Copy link
Collaborator

@taimoorzaeem taimoorzaeem commented Jan 21, 2025

Add new TableNotFound error and add json error
message for this error. Closes #3697, closes #3602.

(Couldn't think of a better changelog/commit message. Feel free to suggest a new/better message).

@taimoorzaeem taimoorzaeem force-pushed the non-existing-table/issue3697 branch from 95d4973 to 52591c0 Compare January 21, 2025 14:26
CHANGELOG.md Outdated Show resolved Hide resolved
@steve-chavez
Copy link
Member

Now that we rely on the schema cache for simple table filters, we need to make sure these requests are fast when a schema cache load for relationships is slow (#3046).

There's a test that validates the above behavior (a request with resource embedding is blocked until the schema cache finishes loading):

def test_requests_wait_for_schema_cache_reload(defaultenv):
"requests that use the schema cache (e.g. resource embedding) wait for the schema cache to reload"
env = {
**defaultenv,
"PGRST_DB_SCHEMAS": "apflora",
"PGRST_DB_POOL": "2",
"PGRST_DB_ANON_ROLE": "postgrest_test_anonymous",
"PGRST_SERVER_TIMING_ENABLED": "true",
}
with run(env=env, wait_max_seconds=30) as postgrest:
# reload the schema cache
response = postgrest.session.get("/rpc/notify_pgrst")
assert response.status_code == 204
postgrest.wait_until_scache_starts_loading()
response = postgrest.session.get("/tpopmassn?select=*,tpop(*)")
assert response.status_code == 200
plan_dur = parse_server_timings_header(response.headers["Server-Timing"])[
"plan"
]
assert plan_dur > 10000.0

We need an additional test that asserts that a table request (with no resource embedding) finishes in a short plan_dur after reloading the schema cache (calling /rpc/notify_pgrst in the test).

test/spec/Feature/Query/DeleteSpec.hs Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
@taimoorzaeem taimoorzaeem marked this pull request as draft January 22, 2025 15:16
@taimoorzaeem taimoorzaeem force-pushed the non-existing-table/issue3697 branch from f008e21 to bdaf6bf Compare January 23, 2025 08:19
@taimoorzaeem taimoorzaeem marked this pull request as ready for review January 23, 2025 08:30
@taimoorzaeem
Copy link
Collaborator Author

taimoorzaeem commented Jan 24, 2025

One last concern, we are still using NotFound error in a couple places, which returns an empty error json:

toJSON NotFound = JSON.object []

This seems fine for now, but maybe should be improved later (add error msg, details etc) for better UX?

@taimoorzaeem taimoorzaeem force-pushed the non-existing-table/issue3697 branch 3 times, most recently from 8d6bb71 to bb4f692 Compare February 1, 2025 07:43
@taimoorzaeem taimoorzaeem force-pushed the non-existing-table/issue3697 branch from bb4f692 to 7196aa5 Compare February 5, 2025 05:56
@taimoorzaeem
Copy link
Collaborator Author

taimoorzaeem commented Feb 7, 2025

@steve-chavez Could this get a review? Seems good to me.

* Add new `TableNotFound` error with error code PGRST205

* Closes PostgREST#3697, PostgREST#3602.
@@ -253,6 +255,12 @@ instance JSON.ToJSON ApiRequestError where
toJSON (ColumnNotFound relName colName) = toJsonPgrstError
SchemaCacheErrorCode04 ("Could not find the '" <> colName <> "' column of '" <> relName <> "' in the schema cache") Nothing Nothing

toJSON (TableNotFound schemaName relName tbls) = toJsonPgrstError
SchemaCacheErrorCode05
("Could not find relation '" <> schemaName <> "." <> relName <> "' in the schema cache")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "relation" term might be confused with "relationship". I think we can be more precise here and instead refer to "table" or "view", we have a tableIsView :: Bool field already.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it doesn't make sense to discriminate table or view if we don't know what we're looking for. Maybe you could omit the "relation" term altogether, or change it to "table or view".

-- Do a fuzzy search in all tables in the same schema and return closest result
tableNotFoundHint :: Text -> Text -> [Table] -> Maybe Text
tableNotFoundHint schema tblName tblList
= fmap (\tbl -> "Perhaps you meant the relation '" <> schema <> "." <> tbl <> "'") perhapsTable
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto on "relation"

Comment on lines +329 to +330
readPlan :: Bool -> QualifiedIdentifier -> AppConfig -> SchemaCache -> ApiRequest -> Either Error ReadPlanTree
readPlan fromCallPlan qi@QualifiedIdentifier{..} AppConfig{configDbMaxRows, configDbAggregates} SchemaCache{dbTables, dbRelationships, dbRepresentations} apiRequest =
Copy link
Member

@steve-chavez steve-chavez Feb 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Bool here is confusing, looks like it breaks the abstraction. Is there another way to do this?

Let's try and do it correctly now, even if it requires a refactor. Otherwise tech debt accrues and refactors become more laborious later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try and do it correctly now, even if it requires a refactor. Otherwise tech debt accrues and refactors become more laborious later.

Agreed.

@taimoorzaeem taimoorzaeem marked this pull request as draft February 10, 2025 11:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants